<?php

defined('BASEPATH') or die('forbidden');

/**
 * 错误类
 * @author  Karson
 * @name    error.php
 * @since   2012-3-6 20:00:07
 */
class Error {

    var $action;
    var $severity;
    var $message;
    var $filename;
    var $line;
    var $ob_level;
    var $levels = array(
        E_ERROR => 'Error',
        E_WARNING => 'Warning',
        E_PARSE => 'Parsing Error',
        E_NOTICE => 'Notice',
        E_CORE_ERROR => 'Core Error',
        E_CORE_WARNING => 'Core Warning',
        E_COMPILE_ERROR => 'Compile Error',
        E_COMPILE_WARNING => 'Compile Warning',
        E_USER_ERROR => 'User Error',
        E_USER_WARNING => 'User Warning',
        E_USER_NOTICE => 'User Notice',
        E_STRICT => 'Runtime Notice'
    );

    function Error() {
        $framework = &get_instance('controller');
        $this->config = &$framework->config;
        $this->db = &$framework->db;
        if (isset($framework->auth)) {
            $this->auth = &$framework->auth;
        }
        $this->ob_level = ob_get_level();
    }

    /**
     * 记录错误数据
     * @param contstant $severity 错误等级
     * @param string $message 错误数据
     * @param string $filepath 错误文件地址
     * @param int $line 错误行数
     */
    function log_error($severity, $message, $filepath, $line) {
        $severity = (!isset($this->levels[$severity])) ? $severity : $this->levels[$severity];
        log_message('系统错误[' . $this->get_ip() . '] --> ' . '级别: ' . $severity . '  --> ' . $message . ' ' . $filepath . ' --> 行号:' . $line . "--> http://" . $_SERVER ['HTTP_HOST'] . urldecode($_SERVER['REQUEST_URI']), 'error');
    }

    /**
     * 404文件未找到
     * @param string $page 错误文件
     */
    function show_404($page = '') {
        echo $this->show_error('查看的文件未找到', "查看的文件[$page]未找到", 'error_404', 404);
        exit;
    }

    /**
     * 显示常规错误
     * @param string $heading 错误信息
     * @param string $message 错误数据
     * @param string $template 错误模板
     * @param int $code 错误代号
     * @return string 错误的信息
     */
    function show_error($heading, $message, $template = 'error_general', $code = 500) {
        headers_sent() or header("HTTP/1.0 {$code} Error");
        log_message('应用错误[' . $this->get_ip() . '] --> ' . $message . ' --> ' . "http://" . $_SERVER ['HTTP_HOST'] . urldecode($_SERVER['REQUEST_URI']), 'error');
        $message = '<p>' . implode('</p><p>', (!is_array($message)) ? array($message) : $message) . '</p>';
        if (ob_get_level() > $this->ob_level + 1)
            ob_end_flush();
        ob_start();
        include(APPPATH . 'errors/' . $template . '.php');
        $buffer = ob_get_contents();
        ob_end_clean();
        return $buffer;
    }

    /**
     * 显示PHP常规错误
     * @param contstant $severity 错误等级
     * @param string $message 错误内容
     * @param string $filepath 错误文件位置
     * @param int $line 错误行数
     */
    function show_php_error($severity, $message, $filepath, $line, $template = 'error_php') {
        $severity = (!isset($this->levels[$severity])) ? $severity : $this->levels[$severity];
        $filepath = str_replace("\\", "/", $filepath);
        if (FALSE !== strpos($filepath, '/')) {
            $x = explode('/', $filepath);
            $filepath = $x[count($x) - 2] . '/' . end($x);
        }
        $this->log_error($severity, $message, $filepath, $line);
        //如果是警告或通知型错误就不打印出来
        if (in_array($severity, array('Warning', 'Notice')))
            return true;
        if (ob_get_level() > $this->ob_level + 1)
            ob_end_flush();
        ob_start();
        include(APPPATH . 'errors/' . $template . '.php');
        $buffer = ob_get_contents();
        ob_end_clean();
        echo $buffer;
    }

    function get_ip() {
        if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
            $cip = $_SERVER["HTTP_CLIENT_IP"];
        } else if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            $cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        } else if (!empty($_SERVER["REMOTE_ADDR"])) {
            $cip = $_SERVER["REMOTE_ADDR"];
        } else {
            $cip = '';
        }
        preg_match("/[\d\.]{7,15}/", $cip, $cips);
        $cip = isset($cips[0]) ? $cips[0] : 'unknown';
        unset($cips);
        return $cip;
    }

}